package com.yutian.example.demo.forum.aop;

import com.yutian.example.demo.common.vo.IBaseRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 打印日志、校验参数
 */
@Slf4j
@Aspect
@Component
public class ForumServiceAop {

    @PostConstruct
    public void init(){
        log.info("--- ForumServiceAop init ---");
    }

    @Pointcut("execution(public * com.yutian.example.demo.forum.service..*ServiceImpl.*(..))")
    public void api() {
    }

    @Around("api()")
    public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
        long begin = System.currentTimeMillis();

        Class<?> clazz = pjp.getSignature().getDeclaringType();
        String className = clazz.getName();
        String methodName = pjp.getSignature().getName();
        Object[] arguments = pjp.getArgs();

        checkAndLogBaseRequest(className, methodName, arguments);
        Object rsp = pjp.proceed();
        log.info("{} | {} cost time:{}", className, methodName, (System.currentTimeMillis() - begin));
        return rsp;
    }



    public void checkAndLogBaseRequest(String className, String methodName, Object... params) {
        if (ArrayUtils.isEmpty(params)) {
            return;
        }
        for (Object object : params) {
            if (null == object) {
                continue;
            }
            if (object.getClass().isArray()) {
                Object[] objectArr = (Object[]) object;
                if (ArrayUtils.isNotEmpty(objectArr)) {
                    for (Object item : objectArr) {
                        checkAndLogBaseRequest(className, methodName, new Object[] { item });
                    }
                }
            } else if ((object instanceof IBaseRequest)) {
                try {
                    // 打印请求日志
                    log.info("{} | {} 入参: {}", className, methodName, object);
                } catch (Exception e) {
                    log.error("切面打印请求失败", e);
                }
                ((IBaseRequest) object).check();
            }
        }
    }

}
